<template>
  <div class="dropdown-contianer" @click.stop="handleDropdownClick" ref="contianerRef">
    <slot> </slot>

    <Transition name="fade">
      <template v-if="isShow">
        <div class="dropdown-list" :style="{ ...dropdownStyle }" ref="outRef">
          <slot name="list"></slot>
        </div>
      </template>
    </Transition>
  </div>
</template>

<script lang="ts" setup>
import { ref, watch, computed } from 'vue'
import { onClickOutside, useElementHover } from '@vueuse/core' // 依赖vueuse插件里的个别功能
// ====== props
interface IProps {
  dropdownStyle?: object
  openWay?: 'click' | 'hover' | 'none'
}
const props = withDefaults(defineProps<IProps>(), {
  openWay: 'hover'
})

// ====== data
const isShow = ref<boolean>(false)
const outRef = ref<any>(null)
const contianerRef = ref<any>(null)

// ====== vueuse
// 支持点击内容区域外部关闭弹窗
onClickOutside(contianerRef, (_e: Event) => {
  closeDropdown()
})
const isHovered = useElementHover(contianerRef)

// ====== computed
const isShowCpt = computed(() => isShow.value)

// ====== watch
watch(isHovered, newVal => {
  if (props.openWay === 'hover') {
    if (newVal) {
      openDropdown()
    } else {
      closeDropdown()
    }
  }
})

// ====== methods
const openDropdown = () => {
  if (isShow.value) return

  isShow.value = true
}
const closeDropdown = (cb?: () => void) => {
  if (!isShow.value) return

  isShow.value = false
  cb && cb()
}
const handleDropdownClick = () => {
  if (isShow.value) return

  if (props.openWay === 'click') {
    openDropdown()
  }
}

// ====== expose
defineExpose({
  isShowCpt,
  openDropdown,
  closeDropdown
})
</script>

<style lang="less" scoped>
.dropdown-contianer {
  position: relative;

  .dropdown-list {
    position: absolute;
    left: 0;
    top: 60px;
    min-width: 100px;
    min-height: 100px;
    width: 100%;
    background: #ffffff;
    box-shadow: 0 0 5px 1px rgba(0, 0, 0, 0.1);
    border-radius: 5px;
    z-index: 1997;
  }

  .dropdown-list::before {
    content: '';
    position: absolute;
    left: 0;
    top: -10px; // 10px空隙
    width: 100%;
    height: 10px; // 10px空隙
    background: transparent;
  }
}

.fade-enter-active,
.fade-leave-active {
  transition: all 0.3s ease;
}
.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}
</style>
